package org.peterf.foxish.component;

import org.peterf.foxish.R;
import org.peterf.foxish.buffer.IndexBufferB;
import org.peterf.foxish.buffer.VertexBufferF;
import org.peterf.foxish.camera.Camera;
import org.peterf.foxish.opengl20.OpenGLUtil.BufferUsage;
import org.peterf.foxish.program.ProgramRepository;
import org.peterf.foxish.texture.SlicedTexture;
import org.peterf.foxish.texture.Texture;
import org.peterf.foxish.texture.TextureRepository;
import org.peterf.foxish.texture.TextureUtil;

import android.graphics.BitmapFactory.Options;
import android.opengl.GLES20;
import android.util.Log;

public class TexturedRectangle extends RectangleSprite {

    protected int samplerLoc;

    protected int texLoc;

    protected Texture texture = null;
    
    protected int resId = 0;

    public Texture getTexture() {
        return texture;
    }
    
    public void setTexture(Texture texture) {
        this.texture = texture; 
    }
    
    public TexturedRectangle(Texture texture) {
        this.texture = texture;
        init(null, 0, 0);
    }

    public TexturedRectangle(int resId) {
        this.resId = resId;
        texture = TextureRepository.get(resId);
        init(null, 0, 0);
    }
    
    public TexturedRectangle(SlicedTexture texture, int x, int y) {
        this.texture = texture;
        init(texture, x, y);
    }
    
    private void init(SlicedTexture slice, int x, int y) {
        if (slice != null) {
            x1 = -slice.getCellWidth() >> 1;
            x2 = slice.getCellWidth() >> 1;
            y1 = slice.getCellHeight() >> 1;
            y2 = -slice.getCellHeight() >> 1;
        } else {
            x1 = -texture.getWidth() >> 1;
            x2 = texture.getWidth() >> 1;
            y1 = texture.getHeight() >> 1;
            y2 = -texture.getHeight() >> 1;
        }
        float ps[] = new float[] { x1, y1, 0.0f, 0.0f, x1, -y1, 0.0f, 1.0f, x2,
                -y2, 1.0f, 0.0f, x2, y2, 1.0f, 1.0f };
        if (slice != null) {
            slice.getTextureCoordinate(ps, 2, 4, x, y);
        }
        vertexBuffer = new VertexBufferF(ps, BufferUsage.DYNAMIC);
        byte is[] = new byte[] { 0, 1, 2, 3 };
        indexBuffer = new IndexBufferB(is, BufferUsage.DYNAMIC);
    }
    
    public void updateTextureCoordinate(float src[], int stride, int offset) {
        if (stride == 0) {
            stride = 2;
        }
        ((VertexBufferF) vertexBuffer).update(src, offset, 2, 2);
        ((VertexBufferF) vertexBuffer).update(src, offset + stride, 2, 6);
        ((VertexBufferF) vertexBuffer).update(src, offset + stride * 2, 2, 10);
        ((VertexBufferF) vertexBuffer).update(src, offset + stride * 3, 2, 14);
        vertexBuffer.subUpload();
    }
    
    public void updateCoordinate(float src[], int stride, int offset) {
        if (stride == 0) {
            stride = 2;
        }
        ((VertexBufferF) vertexBuffer).update(src, offset, 2, 0);
        ((VertexBufferF) vertexBuffer).update(src, offset + stride, 2, 4);
        ((VertexBufferF) vertexBuffer).update(src, offset + stride * 2, 2, 8);
        ((VertexBufferF) vertexBuffer).update(src, offset + stride * 3, 2, 12);
        vertexBuffer.subUpload();
    }
    
    @Override
    public void onCreate() {
        onRecreate();
    }

    @Override
    public void onDestroy() {
        vertexBuffer.delete();
        indexBuffer.delete();
        texture.delete();
        program.delete();
    }

    @Override
    public synchronized void onDraw(Camera camera, float elapsed) {
        onUpdate(elapsed);
        if (enabled) {
            program.use(camera);
            program.assignUniformMat4(mvLoc, matrix.getMatrix(), 0);
            program.assignAttrib(posLoc, 16, 0, 2);
            program.assignAttrib(texLoc, 16, 8, 2);
            // TODO Remove GLES20 related.
            GLES20.glUniform1i(samplerLoc, 0);
            GLES20.glUniform1f(colorLoc, color[3]);
            program.drawTriangleStrip(0, 4);
        }
    }

    @Override
    public void onRecreate() {
        vertexBuffer.upload();
        indexBuffer.upload();
        program = ProgramRepository.get(
                R.string.vertex_ucamera_umvtrans_apos_avtex,
                R.string.fragment_usamp_ualpha_vtex);
        program.setBuffer(vertexBuffer, indexBuffer);
        if (resId != 0) {
            texture = TextureRepository.get(resId);
        }
        program.setTexture(texture);
        mvLoc = program.getUniformLoc(R.string.uniform_mvtrans);
        posLoc = program.getAttribLoc(R.string.attrib_position);
        texLoc = program.getAttribLoc(R.string.attrib_texture);
        samplerLoc = program.getUniformLoc(R.string.uniform_sampler);
        colorLoc = program.getUniformLoc(R.string.uniform_alpha);
    }

}
